package com.cm.projectx.controller.analysis.handler;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cm.projectx.common.cache.SystemOrgCache;
import com.cm.projectx.entity.PriceTask;
import com.cm.projectx.entity.ProductPriceReport;
import com.cm.projectx.entity.ProductPriceReportDetail;
import com.cm.projectx.entity.TaskProcessRelation;
import com.cm.projectx.entity.analysis.RespDto;
import com.cm.projectx.entity.analysis.ValueMapPOJO;
import com.cm.projectx.mapper.TaskProcessRelationMapper;
import com.cm.projectx.response.Result;
import com.cm.projectx.service.IPriceTaskService;
import com.cm.projectx.service.IProductPriceReportDetailService;
import com.cm.projectx.service.IProductPriceReportService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Component
public class PersonLifeAndExpenseHandler {

    @Value("${spring.file.template.path}")
    private String templateFilePath;
    @Autowired
    private TaskProcessRelationMapper taskProcessRelationMapper;
    @Autowired
    private IProductPriceReportService productPriceReportService;
    @Autowired
    private IProductPriceReportDetailService productPriceReportDetailService;
    @Autowired
    private IPriceTaskService priceTaskService;

    private List<TaskProcessRelation> getTaskProcessRelations(int taskId, String lastReportDate) {
        return taskProcessRelationMapper.selectList(Wrappers.<TaskProcessRelation>lambdaQuery()
                .eq(TaskProcessRelation::getTaskId, taskId)
                .eq(TaskProcessRelation::getStartTime, lastReportDate));
    }

    public void wrapperResult(Result result, int taskId, String lastReportDate, String nowReportDate, List<RespDto> respDtoList, String productName) {
        PriceTask priceTask = priceTaskService.getById(taskId);
        //参与比较的所有流程信息
        //上期流程
        List<TaskProcessRelation> lastTaskProcessRelations = getTaskProcessRelations(taskId, lastReportDate);
        //当期流程
        List<TaskProcessRelation> nowTaskProcessRelations = getTaskProcessRelations(taskId, nowReportDate);
        //根据流程拿到填报主表的信息
        //上期
        List<ProductPriceReport> lastProductPriceReports = productPriceReportService.list(Wrappers.<ProductPriceReport>lambdaQuery().eq(ProductPriceReport::getWorkflowInstanceStatus, "已完成")
                .in(ProductPriceReport::getProcessId,
                        CollectionUtil.isEmpty(lastTaskProcessRelations)? new Object[]{"0"} :lastTaskProcessRelations.stream().map(TaskProcessRelation::getProcessId).toArray()));
        //当期
        List<ProductPriceReport> nowProductPriceReports = productPriceReportService.list(Wrappers.<ProductPriceReport>lambdaQuery().eq(ProductPriceReport::getWorkflowInstanceStatus, "已完成")
                .in(ProductPriceReport::getProcessId,
                        CollectionUtil.isEmpty(nowTaskProcessRelations)? new Object[]{"0"} : nowTaskProcessRelations.stream().map(TaskProcessRelation::getProcessId).toArray()));
        HashMap<String, String> monitorMap = new HashMap<>();
        lastProductPriceReports.forEach(productPriceReport -> {
            monitorMap.put(productPriceReport.getId(), productPriceReport.getMonitorPoint());
        });
        nowProductPriceReports.forEach(productPriceReport -> {
            monitorMap.put(productPriceReport.getId(), productPriceReport.getMonitorPoint());
        });

        //分别拿到商品填报的详细信息，各类商品平均价,如果productName不为空，增加商品的模糊查询
        //上期
        LambdaQueryWrapper<ProductPriceReportDetail> lastProductPriceReportsQueryWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<ProductPriceReportDetail> nowProductPriceReportsQueryWrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotEmpty(productName)) {
            lastProductPriceReportsQueryWrapper.like(ProductPriceReportDetail::getName, productName);
            nowProductPriceReportsQueryWrapper.like(ProductPriceReportDetail::getName, productName);
        }
        List<ProductPriceReportDetail> lastDetail = productPriceReportDetailService.list(lastProductPriceReportsQueryWrapper
                .in(ProductPriceReportDetail::getParentId,
                        CollectionUtil.isEmpty(lastProductPriceReports)? new Object[]{"0"} : lastProductPriceReports.stream().map(ProductPriceReport::getId).toArray()));
        //当期
        List<ProductPriceReportDetail> nowDetail = productPriceReportDetailService.list(nowProductPriceReportsQueryWrapper
                .in(ProductPriceReportDetail::getParentId,
                        CollectionUtil.isEmpty(nowProductPriceReports)? new Object[]{"0"} : nowProductPriceReports.stream().map(ProductPriceReport::getId).toArray()));
        //获取两次的监测点合集,作为响应结果中的检测点数据
        Set<String> monitorSet = new HashSet<>();
        monitorSet.addAll(lastProductPriceReports.stream().map(ProductPriceReport::getMonitorPoint)
                .collect(Collectors.toSet()));
        monitorSet.addAll(nowProductPriceReports.stream().map(ProductPriceReport::getMonitorPoint)
                .collect(Collectors.toSet()));
        ArrayList<String> monitList = new ArrayList<>(monitorSet);
        result.addData("monitorSet", monitList);
        if (CollectionUtil.isEmpty(nowDetail)) {
            if (CollectionUtil.isNotEmpty(lastDetail)) {
                //上期不为空从上期进行封装,当期值全部为0
                Map<String, List<ProductPriceReportDetail>> lastDetailGroup = lastDetail.stream()
                        .collect(Collectors.groupingBy(detail -> detail.getProductInfoId() + "|" + detail.getMetricType()));
                lastDetailGroup.forEach((key, value) -> {
                    //key是每一个商品id + 指标类型， value是该分组下对应的所有检测点填报信息
                    RespDto respDto = new RespDto();
                    respDto.setProductName(value.get(0).getName());
                    respDto.setProductLevel(value.get(0).getKind());
                    respDto.setProductUnit(value.get(0).getUnit());
                    respDto.setPriceType(value.get(0).getMetricType());
                    respDto.setFrequency(priceTask.getScheduleType());
                    //计算当期平均值，某一个商品某一种指标类型的平均值
                    respDto.addNowMetrics(value.get(0).getMetricType(), "0.0");
                    //计算上期平均值，某一个商品某一种指标类型的平均值
                    Double lastAvg = value.stream().mapToDouble(ProductPriceReportDetail::getPrice).average().orElse(0.0D);
                    respDto.addLastMetrics(value.get(0).getMetricType(), String.valueOf(lastAvg));
                    //计算环比
                    respDto.addCircleValues(value.get(0).getMetricType(), "0.0");
                    //封装所有的监测点,当期还没有价格采集
                    monitList.forEach(monitorPoint -> {
                        respDto.addMonitorPrices(monitorPoint, new ValueMapPOJO(value.get(0).getMetricType(), "0.0"));
                    });
                    respDtoList.add(respDto);
                });
            } else {
                //第一次发起的填报，返回填报点还未采集完成的提示
                result.setCode(-1);
                result.setMsg("填报点还未采集完成");
                return;
            }
        } else {
            //统一完成最后的结果封装
            //根据商品id分组，计算每一个商品的平均价
            Map<String, List<ProductPriceReportDetail>> nowDetailGroup = nowDetail.stream()
                    .collect(Collectors.groupingBy(detail -> detail.getProductInfoId() + "|" + detail.getMetricType()));
            Map<String, List<ProductPriceReportDetail>> lastDetailGroup = lastDetail.stream()
                    .collect(Collectors.groupingBy(detail -> detail.getProductInfoId() + "|" + detail.getMetricType()));
            nowDetailGroup.forEach((key, value) -> {
                //key是每一个商品id + 指标类型， value是该分组下对应的所有检测点填报信息
                RespDto respDto = new RespDto();
                respDto.setProductName(value.get(0).getName());
                respDto.setProductLevel(value.get(0).getKind());
                respDto.setProductUnit(value.get(0).getUnit());
                respDto.setPriceType(value.get(0).getMetricType());
                //商品浮动预警值，已当期下发的为准
                respDto.setFloatValue(value.get(0).getFloatValue());
                respDto.setFrequency(priceTask.getScheduleType());
                //计算当期平均值，某一个商品某一种指标类型的平均值
                Double nowAvg = value.stream().mapToDouble(ProductPriceReportDetail::getPrice).average().orElse(0.0D);
                respDto.addNowMetrics(value.get(0).getMetricType(), String.valueOf(nowAvg));
                //计算上期平均值，某一个商品某一种指标类型的平均值
                List<ProductPriceReportDetail> lastThisDetail = lastDetailGroup.get(key);
                if (CollectionUtil.isEmpty(lastThisDetail)) {
                    respDto.addLastMetrics(value.get(0).getMetricType(), "0.0");
                    respDto.addCircleValues(value.get(0).getMetricType(), nowAvg > 0 ? (int)(nowAvg*100) + ".00%" : "0.00%");
                }else{
                    Double lastAvg = lastThisDetail.stream().mapToDouble(ProductPriceReportDetail::getPrice).average().orElse(0D);
                    respDto.addLastMetrics(value.get(0).getMetricType(), String.valueOf(lastAvg));
                    //计算环比
                    respDto.addCircleValues(value.get(0).getMetricType(), lastAvg > 0 ? (int)((nowAvg - lastAvg) / lastAvg * 100) + ".00%" : "100.0%");
                }
                //封装所有的监测点
                HashSet<String> tempMonitorSet = new HashSet<>();
                value.forEach(detail -> {
                    String monitorPoint = monitorMap.get(detail.getParentId());
                    ValueMapPOJO pojo = new ValueMapPOJO(value.get(0).getMetricType(), String.valueOf(detail.getPrice()));
                    respDto.addMonitorPrices(monitorPoint, pojo);
                    tempMonitorSet.add(monitorPoint);
                });
                monitList.forEach(monitorPoint -> {
                    if (!tempMonitorSet.contains(monitorPoint)) {
                        respDto.addMonitorPrices(monitorPoint, new ValueMapPOJO(value.get(0).getMetricType(), "0"));}
                });
                respDtoList.add(respDto);
            });

        }
    }

    public Map<String, Object> personLifeAndExpensePriceWithSupermarketExportHandler(List<String> monitorList, List<RespDto> priceResult, String fileName) {
        //方法返回excel文件信息
        Map<String, Object> exportFileInfo = new HashMap<>(4);
        //加载模板文件
        //InputStream stream = FileUtil.getInputStream(templateFilePath + fileName);
        XSSFWorkbook workbook;
        workbook = new XSSFWorkbook();
        //设置表头
        Sheet sheet = workbook.createSheet(fileName);
        Row headerRow = sheet.createRow(0);
        List<String> headers = new ArrayList<>();
        headers.add("商品名称");
        headers.add("规格等级");
        headers.add("计量单位");
        headers.add("环比");
        headers.add("上期值");
        headers.add("当期值");
        headers.add("指标类型");
        headers.add("上报频次");
        //监测点名称作为表头
        //从组织机构中获取监测点信息
        headers.addAll(monitorList.stream().map(SystemOrgCache::getOrgName).collect(Collectors.toList()));
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers.get(i));
            CellStyle headerStyle = workbook.createCellStyle();
            Font font = workbook.createFont();
            font.setBold(true); // 字体加粗
            headerStyle.setFont(font);
            headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
            cell.setCellStyle(headerStyle);
        }
        //设置表体
        for (int i = 0; i < priceResult.size(); i++) {
            RespDto respDto = priceResult.get(i);
            Row dataRow = sheet.createRow(i + 1);
            AtomicInteger j = new AtomicInteger();
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductName());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductLevel());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductUnit());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getCircleValues().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getLastMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getNowMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getPriceType());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getFrequency());
            //设置各监测点的当期值
            monitorList.forEach(monitor -> {
                dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getMonitorPriceMapList().get(monitor).get(0).getValue());
            });
        }
        sheet.setColumnWidth(0, 20 * 256);
        for (int i = 0; i < headers.size(); i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, sheet.getColumnWidth(0) + 2 * 256);
        }
        exportFileInfo.put("excel_file_name", fileName);
        exportFileInfo.put("excel_file_content", workbook);
        return exportFileInfo;
    }

    public Map<String, Object> personLifeAndExpensePriceWithMartExportHandler(List<String> monitorList, List<RespDto> priceResult, String fileName) {
        //方法返回excel文件信息
        Map<String, Object> exportFileInfo = new HashMap<>(4);
        //加载模板文件
        //InputStream stream = FileUtil.getInputStream(templateFilePath + fileName);
        XSSFWorkbook workbook;
        workbook = new XSSFWorkbook();
        //设置表头
        Sheet sheet = workbook.createSheet(fileName);
        Row headerRow = sheet.createRow(0);
        List<String> headers = new ArrayList<>();
        headers.add("商品名称");
        headers.add("规格等级");
        headers.add("计量单位");
        headers.add("环比");
        headers.add("上期值");
        headers.add("当期值");
        headers.add("指标类型");
        headers.add("预警阈值");
        //监测点名称作为表头
        //从组织机构中获取监测点信息
        headers.addAll(monitorList.stream().map(SystemOrgCache::getOrgName).collect(Collectors.toList()));
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers.get(i));
            CellStyle headerStyle = workbook.createCellStyle();
            Font font = workbook.createFont();
            font.setBold(true); // 字体加粗
            headerStyle.setFont(font);
            headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
            cell.setCellStyle(headerStyle);
        }
        //设置表体
        for (int i = 0; i < priceResult.size(); i++) {
            RespDto respDto = priceResult.get(i);
            Row dataRow = sheet.createRow(i + 1);
            AtomicInteger j = new AtomicInteger();
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductName());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductLevel());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductUnit());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getCircleValues().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getLastMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getNowMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getPriceType());
            dataRow.createCell(j.getAndIncrement()).setCellValue((int)(Double.parseDouble(respDto.getFloatValue()) * 100) + "%");
            //设置各监测点的当期值
            monitorList.forEach(monitor -> {
                dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getMonitorPriceMapList().get(monitor).get(0).getValue());
            });
        }
        sheet.setColumnWidth(0, 20 * 256);
        for (int i = 0; i < headers.size(); i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, sheet.getColumnWidth(0) + 2 * 256);
        }
        exportFileInfo.put("excel_file_name", fileName);
        exportFileInfo.put("excel_file_content", workbook);
        return exportFileInfo;
    }

    public Map<String, Object> firstTimeReportExportHandler(List<String> monitorList, List<RespDto> priceResult, String fileName) {
        //方法返回excel文件信息
        Map<String, Object> exportFileInfo = new HashMap<>(4);
        //加载模板文件
        //InputStream stream = FileUtil.getInputStream(templateFilePath + fileName);
        XSSFWorkbook workbook;
        workbook = new XSSFWorkbook();
        //设置表头
        Sheet sheet = workbook.createSheet(fileName);

        // 设置表头样式（加粗字体）
        CellStyle headerStyle = workbook.createCellStyle();
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);
        List<String> headers = new ArrayList<>();
        headers.add("商品名称");
        headers.add("规格等级");
        headers.add("计量单位");
        headers.add("预警阈值");
        headers.add("环比");
        headers.add("");
        headers.add("上期平均");
        headers.add("");
        headers.add("当期平均");
        headers.add("");
        List<String> collect = monitorList.stream().map(SystemOrgCache::getOrgName).collect(Collectors.toList());
        collect.forEach(name -> {
            headers.add(name);
            headers.add("");
        });
        Row headerRow1 = sheet.createRow(0);
        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow1.createCell(i);
            cell.setCellValue(headers.get(i));
            cell.setCellStyle(headerStyle);
            if (StringUtils.isEmpty(headers.get(i))) {
                //合并cell
                sheet.addMergedRegion(new CellRangeAddress(0, 0, i-1, i));
            }
        }
        //第二行二级表头
        List<String> headers2 = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            headers2.add("");
        }
        for (int i = 0; i < 3; i++) {
            headers2.add("农贸市场零售价");
            headers2.add("超市零售价");
        }
        collect.forEach(name -> {
            headers2.add("农贸市场零售价");
            headers2.add("超市零售价");
        });
        Row headerRow2 = sheet.createRow(1);
        for (int i = 0; i < headers2.size(); i++) {
            Cell cell = headerRow2.createCell(i);
            cell.setCellValue(headers2.get(i));
            cell.setCellStyle(headerStyle);
            if(i<4){
                sheet.addMergedRegion(new CellRangeAddress(0, 1, i, i));
            }
        }

        //设置表体
        Map<String, List<RespDto>> priceResultGroup = priceResult.stream()
                .collect(Collectors.groupingBy(RespDto::getProductName));

        AtomicInteger rows= new AtomicInteger(2);
        priceResultGroup.forEach((key, value) -> {
            Row dataRow = sheet.createRow(rows.getAndIncrement());
            AtomicInteger j = new AtomicInteger();
            RespDto respDto = value.get(0);
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductName());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductLevel());
            dataRow.createCell(j.getAndIncrement()).setCellValue(respDto.getProductUnit());
            dataRow.createCell(j.getAndIncrement()).setCellValue((int)(Double.parseDouble(respDto.getFloatValue()) * 100) + "%");
            //环比
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "农贸市场零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getCircleValues().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "超市零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getCircleValues().get(0).getValue());
            //上期
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "农贸市场零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getLastMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "超市零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getLastMetrics().get(0).getValue());
            //当期
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "农贸市场零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getNowMetrics().get(0).getValue());
            dataRow.createCell(j.getAndIncrement()).setCellValue(
                    value.stream().filter(one -> "超市零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                            .getNowMetrics().get(0).getValue());
            //设置各监测点的当期值
            monitorList.forEach(monitor -> {
                dataRow.createCell(j.getAndIncrement()).setCellValue(
                        value.stream().filter(one -> "农贸市场零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                                .getMonitorPriceMapList().get(monitor).get(0).getValue());
                dataRow.createCell(j.getAndIncrement()).setCellValue(
                        value.stream().filter(one -> "超市零售价".equals(one.getPriceType())).collect(Collectors.toList()).get(0)
                                .getMonitorPriceMapList().get(monitor).get(0).getValue());
            });
        });
        sheet.setColumnWidth(0, 20 * 256);
        for (int i = 0; i < headers.size(); i++) {
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, sheet.getColumnWidth(0) + 2 * 256);
        }
        exportFileInfo.put("excel_file_name", fileName);
        exportFileInfo.put("excel_file_content", workbook);
        return exportFileInfo;
    }
}
